#include <functional>
#include <string>
#include <vector>
#include <iostream>
class SaleItem;
class Sale{
    using CalcPriceCallback = std::function<double(const std::vector<SaleItem>&)>;
private:
    CalcPriceCallback _calc_cb;
    std::vector<SaleItem> _items;
public:

    std::vector<SaleItem> &Items(){ return _items; }
    double CalculateTotalPrice(){
        if(_calc_cb)
            return _calc_cb(_items);
        return -1.0;
    }
    void RegistCallback(const CalcPriceCallback &cb){
        _calc_cb = cb;
    }
};
struct SaleItem{
    std::string _itemname;
    int _avilablecnt;
    int _price;
};

class Discount{
private:
    double _rate;
    Sale *_sale;        //外界表单
public:
    void SetRate(double rate, Sale *sale){ _rate = rate; _sale = sale; }
    double CalculateTotalPrice() {
        std::cout << "Discount: _rate:" << _rate << std::endl;
        int sum = 0;
        std::vector<SaleItem> items = _sale->Items();
        for(const SaleItem &item:items){
            sum += item._price;
        }
        return sum * _rate;
    }
    void Confirm(){
        _sale->RegistCallback(std::bind(&Discount::CalculateTotalPrice, this));
    }
};

class FullReduction{
private:
    double _enough_line;
    double _reduction;
    Sale *_sale;
public:
    void SetUp(double enough_line, double reduction, Sale *sale){
        _enough_line = enough_line;
        _reduction = reduction;
        _sale = sale;
    }
    double CalculateTotalPrice(){
        std::cout << "FullReduction: _enought_line:" << _enough_line << "_reduction" << _reduction << std::endl;
        int sum = 0;
        std::vector<SaleItem> items = _sale->Items();
        for(const SaleItem &item:items){
            sum += item._price;
        }
        return sum >= _enough_line ? sum - _reduction : sum;
    }
    void Confirm(){
        _sale->RegistCallback(std::bind(&FullReduction::CalculateTotalPrice, this));
    }
};